package org.yi.fc.security.shiro;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.util.WebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 带验证码的表单的表单认证过滤器
 * @author ilgql
 *
 */
public class CaptchaFormAuthenticationFilter extends FormAuthenticationFilter {

	private Logger logger = LoggerFactory.getLogger(getClass());
	
	public static final String CAPTCH_KEY = "vCode";
	
//	public static String DEFAULT_LOGIN_URL = "/admin/login";
	
	
	@Override
	protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {
		
		this.setLoginUrl("/admin/loing");;
		
		Subject subject = getSubject(request, response);
		UsernamePasswordToken token = new UsernamePasswordToken(getUsername(request),getPassword(request));
		
		if(subject.isAuthenticated()){
			return true;
		}
		
		boolean result = false;
		
		try{
			result = doCaptchaValidate(request, CAPTCH_KEY);
		}catch(AuthenticationException e){
			result=  onLoginFailure(token, e, request, response);
		}
		
		return result;
	}
	
	/**
	 * 获取客户端验证码
	 * @param request
	 * @param captchKey 
	 * @return
	 */
	private final String getClientCapthcaCode(ServletRequest request, String captchKey){
		return WebUtils.getCleanParam(request, captchKey);
	}
	
	/**
	 * 获取服务器端生成的验证码
	 * @param request
	 * @return
	 */
	private final String getServerCapthcCode(ServletRequest request){
		return String.valueOf(WebUtils.toHttp(request).getSession().getAttribute(CAPTCH_KEY));
	}
	
	/**
	 * 验证校验码
	 * @param request
	 * @param captchKey			验证码key
	 * @return
	 */
	private boolean doCaptchaValidate(ServletRequest request, String captchKey) throws AuthenticationException {
		String clientCode = getClientCapthcaCode(request, captchKey);
		String serverCode = getServerCapthcCode(request);
		
		if(clientCode == null || serverCode == null){
			logger.error("验证码验证失败，客户端验证码【{}】或者服务端验证码【{}】为空", clientCode, serverCode);
			return false;
		}
		
		if(clientCode.equals(serverCode)){
			return true;
		}else{
			logger.error("验证码验证失败，客户端验证码【{}】,服务端验证码【{}】", clientCode, serverCode);
			throw new AuthenticationException( "验证码验证失败，客户端验证码【" + clientCode + "】,服务端验证码【" + serverCode  + "】");
		}
		
	}
}
